/**
 * @file snakeapiclient.cpp
 * @brief Snake游戏专用API客户端类实现文件
 *
 * 实现Snake游戏的所有API调用功能，包括：
 * - 游戏服务器发现和选择
 * - 游戏认证和会话管理
 * - 房间创建和管理
 * - 游戏统计和排行榜
 * - 玩家配置和设置
 */

#include "../include/snakeapiclient.h"
#include "../include/config.h"
#include <QDebug>               // 调试输出
#include <QJsonDocument>        // JSON文档处理
#include <QJsonArray>           // JSON数组处理
#include <QCoreApplication>     // 应用程序信息
#include <QSysInfo>             // 系统信息

/**
 * @brief SnakeApiClient构造函数
 * @param parent 父对象指针
 *
 * 初始化Snake游戏API客户端：
 * 1. 创建通用API客户端
 * 2. 设置API网关URL
 * 3. 建立信号槽连接
 */
SnakeApiClient::SnakeApiClient(QObject *parent)
    : QObject(parent)
    , m_apiClient(nullptr)
{
    // === 创建通用API客户端 ===
    QString apiGatewayUrl = Config::getApiBaseUrl();
    m_apiClient = new ApiClient(apiGatewayUrl, this);
    
    // === 建立信号槽连接 ===
    connect(m_apiClient, &ApiClient::requestFinished,
            this, &SnakeApiClient::onApiResponse);
    
    qDebug() << "SnakeApiClient initialized with gateway URL:" << apiGatewayUrl;
}

/**
 * @brief SnakeApiClient析构函数
 */
SnakeApiClient::~SnakeApiClient()
{
    qDebug() << "SnakeApiClient destroyed";
}

/**
 * @brief 设置API网关URL
 * @param gatewayUrl API网关的基础URL
 */
void SnakeApiClient::setApiGatewayUrl(const QString &gatewayUrl)
{
    // 重新创建API客户端
    if (m_apiClient) {
        m_apiClient->deleteLater();
    }
    
    m_apiClient = new ApiClient(gatewayUrl, this);
    connect(m_apiClient, &ApiClient::requestFinished,
            this, &SnakeApiClient::onApiResponse);
    
    qDebug() << "API Gateway URL updated to:" << gatewayUrl;
}

/**
 * @brief 设置认证令牌
 * @param accessToken 访问令牌
 */
void SnakeApiClient::setAccessToken(const QString &accessToken)
{
    if (m_apiClient) {
        m_apiClient->setToken(accessToken);
    }
}

/**
 * @brief 获取可用的游戏服务器列表
 * @param region 地区筛选（可选）
 * @param gameType 游戏类型（默认"snake"）
 */
void SnakeApiClient::getAvailableGameServers(const QString &region, const QString &gameType)
{
    QString endpoint = buildEndpoint("/snake/servers/available");
    
    QJsonObject params;
    if (!region.isEmpty()) {
        params["region"] = region;
    }
    if (!gameType.isEmpty()) {
        params["game_type"] = gameType;
    }
    
    qDebug() << "Requesting available game servers, region:" << region << "gameType:" << gameType;
    m_apiClient->get(endpoint, params);
}

/**
 * @brief 获取推荐的游戏服务器
 * @param region 首选地区
 */
void SnakeApiClient::getRecommendedGameServer(const QString &region)
{
    QString endpoint = buildEndpoint("/snake/servers/recommended");
    
    QJsonObject params;
    if (!region.isEmpty()) {
        params["region"] = region;
    }
    
    qDebug() << "Requesting recommended game server, region:" << region;
    m_apiClient->get(endpoint, params);
}

/**
 * @brief 游戏登录
 * @param gameType 游戏类型
 * @param preferredServerId 首选服务器ID（可选）
 * @param clientInfo 客户端信息
 */
void SnakeApiClient::gameLogin(const QString &gameType, 
                              const QString &preferredServerId,
                              const QJsonObject &clientInfo)
{
    QString endpoint = buildEndpoint("/auth/game/login");
    
    QJsonObject data;
    data["game_type"] = gameType;
    
    if (!preferredServerId.isEmpty()) {
        data["preferred_server_id"] = preferredServerId;
    }
    
    // === 添加客户端信息 ===
    QJsonObject fullClientInfo = buildClientInfo();
    if (!clientInfo.isEmpty()) {
        // 合并用户提供的客户端信息
        for (auto it = clientInfo.begin(); it != clientInfo.end(); ++it) {
            fullClientInfo[it.key()] = it.value();
        }
    }
    data["client_info"] = fullClientInfo;
    
    // === 添加其他必要信息 ===
    data["client_ip"] = "127.0.0.1"; // 实际应用中应获取真实IP
    data["user_agent"] = QString("%1/%2")
                        .arg(QCoreApplication::applicationName())
                        .arg(QCoreApplication::applicationVersion());
    
    qDebug() << "Performing game login, gameType:" << gameType << "preferredServer:" << preferredServerId;
    m_apiClient->post(endpoint, data);
}

/**
 * @brief 验证游戏令牌
 * @param gameToken 游戏令牌
 */
void SnakeApiClient::validateGameToken(const QString &gameToken)
{
    QString endpoint = buildEndpoint("/auth/game/validate");
    
    QJsonObject data;
    data["game_token"] = gameToken;
    
    qDebug() << "Validating game token";
    m_apiClient->post(endpoint, data);
}

/**
 * @brief 刷新游戏令牌
 * @param gameToken 当前游戏令牌
 */
void SnakeApiClient::refreshGameToken(const QString &gameToken)
{
    QString endpoint = buildEndpoint("/auth/game/refresh");
    
    QJsonObject data;
    data["game_token"] = gameToken;
    
    qDebug() << "Refreshing game token";
    m_apiClient->post(endpoint, data);
}

/**
 * @brief 获取房间列表
 * @param status 房间状态筛选（可选）
 * @param gameMode 游戏模式筛选（可选）
 * @param limit 返回数量限制
 * @param offset 分页偏移
 */
void SnakeApiClient::getRoomList(const QString &status, int gameMode, int limit, int offset)
{
    QString endpoint = buildEndpoint("/snake/rooms");
    
    QJsonObject params;
    if (!status.isEmpty()) {
        params["status"] = status;
    }
    if (gameMode >= 0) {
        params["game_mode"] = gameMode;
    }
    if (limit > 0) {
        params["limit"] = limit;
    }
    if (offset > 0) {
        params["offset"] = offset;
    }
    
    qDebug() << "Requesting room list, status:" << status << "gameMode:" << gameMode;
    m_apiClient->get(endpoint, params);
}

/**
 * @brief 获取房间详细信息
 * @param roomId 房间ID
 */
void SnakeApiClient::getRoomInfo(const QString &roomId)
{
    QString endpoint = buildEndpoint(QString("/snake/rooms/%1").arg(roomId));
    
    qDebug() << "Requesting room info for room:" << roomId;
    m_apiClient->get(endpoint);
}

/**
 * @brief 创建房间（HTTP API方式）
 * @param roomName 房间名称
 * @param config 房间配置
 */
void SnakeApiClient::createRoom(const QString &roomName, const QJsonObject &config)
{
    QString endpoint = buildEndpoint("/snake/rooms");
    
    QJsonObject data;
    data["room_name"] = roomName;
    data["max_players"] = config.contains("max_players") ? config["max_players"].toInt() : 4;
    data["game_mode"] = config.contains("game_mode") ? config["game_mode"].toInt() : 1;
    data["map_width"] = config.contains("map_width") ? config["map_width"].toInt() : 40;
    data["map_height"] = config.contains("map_height") ? config["map_height"].toInt() : 30;
    data["game_speed_ms"] = config.contains("game_speed_ms") ? config["game_speed_ms"].toInt() : 100;
    data["enable_walls"] = config.contains("enable_walls") ? config["enable_walls"].toBool() : true;
    data["enable_special_foods"] = config.contains("enable_special_foods") ? config["enable_special_foods"].toBool() : false;
    data["max_food_count"] = config.contains("max_food_count") ? config["max_food_count"].toInt() : 10;
    
    qDebug() << "Creating room:" << roomName;
    m_apiClient->post(endpoint, data);
}

/**
 * @brief 获取玩家统计信息
 * @param playerId 玩家ID（可选，默认当前玩家）
 */
void SnakeApiClient::getPlayerStats(const QString &playerId)
{
    QString endpoint;
    if (playerId.isEmpty()) {
        endpoint = buildEndpoint("/snake/stats/player");
    } else {
        endpoint = buildEndpoint(QString("/snake/stats/player/%1").arg(playerId));
    }
    
    qDebug() << "Requesting player stats for player:" << (playerId.isEmpty() ? "current" : playerId);
    m_apiClient->get(endpoint);
}

/**
 * @brief 获取排行榜
 * @param type 排行榜类型
 * @param limit 返回数量限制
 * @param offset 分页偏移
 */
void SnakeApiClient::getLeaderboard(const QString &type, int limit, int offset)
{
    QString endpoint = buildEndpoint("/snake/leaderboard");
    
    QJsonObject params;
    params["type"] = type;
    if (limit > 0) {
        params["limit"] = limit;
    }
    if (offset > 0) {
        params["offset"] = offset;
    }
    
    qDebug() << "Requesting leaderboard, type:" << type;
    m_apiClient->get(endpoint, params);
}

/**
 * @brief 获取游戏历史记录
 * @param playerId 玩家ID（可选）
 * @param limit 返回数量限制
 * @param offset 分页偏移
 */
void SnakeApiClient::getGameHistory(const QString &playerId, int limit, int offset)
{
    QString endpoint;
    if (playerId.isEmpty()) {
        endpoint = buildEndpoint("/snake/history");
    } else {
        endpoint = buildEndpoint(QString("/snake/history/%1").arg(playerId));
    }
    
    QJsonObject params;
    if (limit > 0) {
        params["limit"] = limit;
    }
    if (offset > 0) {
        params["offset"] = offset;
    }
    
    qDebug() << "Requesting game history for player:" << (playerId.isEmpty() ? "current" : playerId);
    m_apiClient->get(endpoint, params);
}

/**
 * @brief 获取游戏配置
 */
void SnakeApiClient::getGameConfig()
{
    QString endpoint = buildEndpoint("/snake/config");
    
    qDebug() << "Requesting game config";
    m_apiClient->get(endpoint);
}

/**
 * @brief 更新玩家配置
 * @param config 玩家配置
 */
void SnakeApiClient::updatePlayerConfig(const QJsonObject &config)
{
    QString endpoint = buildEndpoint("/snake/config/player");
    
    qDebug() << "Updating player config";
    m_apiClient->put(endpoint, config);
}

/**
 * @brief 获取玩家配置
 */
void SnakeApiClient::getPlayerConfig()
{
    QString endpoint = buildEndpoint("/snake/config/player");

    qDebug() << "Requesting player config";
    m_apiClient->get(endpoint);
}

/**
 * @brief 处理API响应
 * @param endpoint API端点
 * @param response API响应
 */
void SnakeApiClient::onApiResponse(const QString &endpoint, const ApiClient::ApiResponse &response)
{
    qDebug() << "Received API response for endpoint:" << endpoint << "success:" << response.success;

    if (!response.success) {
        emit apiError(endpoint, response.errorMessage);
        return;
    }

    // === 根据端点分发响应处理 ===
    if (endpoint.contains("/snake/servers/available")) {
        handleGameServersResponse(response);
    } else if (endpoint.contains("/snake/servers/recommended")) {
        handleGameServersResponse(response);
    } else if (endpoint.contains("/auth/game/login")) {
        handleGameLoginResponse(response);
    } else if (endpoint.contains("/auth/game/validate")) {
        if (response.success) {
            emit gameTokenValidated(response.data);
        } else {
            emit gameTokenValidationFailed(response.errorMessage);
        }
    } else if (endpoint.contains("/snake/rooms") && !endpoint.contains("/snake/rooms/")) {
        handleRoomListResponse(response);
    } else if (endpoint.contains("/snake/rooms/")) {
        // 单个房间信息
        RoomInfo roomInfo = parseRoomInfo(response.data);
        emit roomInfoReceived(roomInfo);
    } else if (endpoint.contains("/snake/stats/player")) {
        handlePlayerStatsResponse(response);
    } else if (endpoint.contains("/snake/leaderboard")) {
        handleLeaderboardResponse(response);
    } else if (endpoint.contains("/snake/history")) {
        QJsonArray history = response.data["history"].toArray();
        emit gameHistoryReceived(history);
    } else if (endpoint.contains("/snake/config") && !endpoint.contains("/snake/config/player")) {
        handleGameConfigResponse(response);
    } else if (endpoint.contains("/snake/config/player")) {
        if (endpoint.endsWith("/snake/config/player")) {
            // GET请求 - 获取玩家配置
            emit playerConfigReceived(response.data);
        } else {
            // PUT请求 - 更新玩家配置
            emit playerConfigUpdated();
        }
    }
}

/**
 * @brief 处理游戏服务器响应
 * @param response API响应
 */
void SnakeApiClient::handleGameServersResponse(const ApiClient::ApiResponse &response)
{
    QJsonObject data = response.data;
    QJsonArray serversArray = data["servers"].toArray();
    QString recommendedServerId = data["recommended_server"].toString();

    QList<GameServerInfo> servers;
    for (const QJsonValue &serverValue : serversArray) {
        QJsonObject serverObj = serverValue.toObject();
        GameServerInfo serverInfo = parseGameServerInfo(serverObj);
        servers.append(serverInfo);
    }

    qDebug() << "Parsed" << servers.size() << "game servers, recommended:" << recommendedServerId;
    emit gameServersReceived(servers, recommendedServerId);

    // 如果是推荐服务器请求，额外发送推荐服务器信号
    if (!servers.isEmpty() && !recommendedServerId.isEmpty()) {
        for (const GameServerInfo &server : servers) {
            if (server.serverId == recommendedServerId) {
                emit recommendedServerReceived(server);
                break;
            }
        }
    }
}

/**
 * @brief 处理游戏登录响应
 * @param response API响应
 */
void SnakeApiClient::handleGameLoginResponse(const ApiClient::ApiResponse &response)
{
    if (response.success) {
        GameLoginResult loginResult = parseGameLoginResult(response.data);
        m_currentGameToken = loginResult.gameToken;
        m_currentPlayerId = loginResult.playerId;

        qDebug() << "Game login successful, player ID:" << loginResult.playerId;
        emit gameLoginSucceeded(loginResult);
    } else {
        qDebug() << "Game login failed:" << response.errorMessage;
        emit gameLoginFailed(response.errorMessage);
    }
}

/**
 * @brief 处理房间列表响应
 * @param response API响应
 */
void SnakeApiClient::handleRoomListResponse(const ApiClient::ApiResponse &response)
{
    QJsonObject data = response.data;
    QJsonArray roomsArray = data["rooms"].toArray();
    int totalCount = data["total_count"].toInt();

    QList<RoomInfo> rooms;
    for (const QJsonValue &roomValue : roomsArray) {
        QJsonObject roomObj = roomValue.toObject();
        RoomInfo roomInfo = parseRoomInfo(roomObj);
        rooms.append(roomInfo);
    }

    qDebug() << "Parsed" << rooms.size() << "rooms, total count:" << totalCount;
    emit roomListReceived(rooms, totalCount);
}

/**
 * @brief 处理玩家统计响应
 * @param response API响应
 */
void SnakeApiClient::handlePlayerStatsResponse(const ApiClient::ApiResponse &response)
{
    PlayerStats stats = parsePlayerStats(response.data);
    qDebug() << "Parsed player stats for player:" << stats.playerId;
    emit playerStatsReceived(stats);
}

/**
 * @brief 处理排行榜响应
 * @param response API响应
 */
void SnakeApiClient::handleLeaderboardResponse(const ApiClient::ApiResponse &response)
{
    QJsonObject data = response.data;
    QJsonArray leaderboard = data["leaderboard"].toArray();
    QString type = data["type"].toString();

    qDebug() << "Parsed leaderboard with" << leaderboard.size() << "entries, type:" << type;
    emit leaderboardReceived(leaderboard, type);
}

/**
 * @brief 处理游戏配置响应
 * @param response API响应
 */
void SnakeApiClient::handleGameConfigResponse(const ApiClient::ApiResponse &response)
{
    QJsonObject config = response.data["config"].toObject();
    qDebug() << "Parsed game config";
    emit gameConfigReceived(config);
}

/**
 * @brief 解析游戏服务器信息
 * @param serverData 服务器数据JSON
 * @return 游戏服务器信息结构
 */
SnakeApiClient::GameServerInfo SnakeApiClient::parseGameServerInfo(const QJsonObject &serverData)
{
    GameServerInfo info;
    info.serverId = serverData["server_id"].toString();
    info.host = serverData["host"].toString();
    info.port = serverData["port"].toInt();
    info.websocketPort = serverData["websocket_port"].toInt();
    info.region = serverData["region"].toString();
    info.currentPlayers = serverData["current_players"].toInt();
    info.maxPlayers = serverData["max_players"].toInt();
    info.currentRooms = serverData["current_rooms"].toInt();
    info.maxRooms = serverData["max_rooms"].toInt();
    info.serverLoad = serverData["server_load"].toDouble();
    info.status = serverData["status"].toString();
    info.lastUpdated = serverData["last_updated"].toVariant().toLongLong();

    return info;
}

/**
 * @brief 解析游戏登录结果
 * @param loginData 登录结果JSON
 * @return 游戏登录结果结构
 */
SnakeApiClient::GameLoginResult SnakeApiClient::parseGameLoginResult(const QJsonObject &loginData)
{
    GameLoginResult result;

    // 根据API文档，服务器返回session_token
    result.sessionToken = loginData["session_token"].toString();
    result.gameToken = loginData["game_token"].toString(); // 保持兼容性

    // 解析玩家信息
    QJsonObject playerInfo = loginData["player_info"].toObject();
    result.playerId = playerInfo["player_id"].toString();

    // 解析服务器信息并构建WebSocket URL
    QJsonObject serverInfo = loginData["server_info"].toObject();
    QString host = serverInfo["host"].toString();
    int websocketPort = serverInfo["websocket_port"].toInt();
    result.websocketUrl = QString("ws://%1:%2").arg(host).arg(websocketPort);
    result.sessionId = loginData["session_id"].toString(); // 如果有的话
    result.playerProfile = loginData["player_profile"].toObject();
    result.expiresAt = loginData["expires_at"].toVariant().toLongLong();

    // 解析服务器信息
    result.serverInfo = parseGameServerInfo(serverInfo);

    qDebug() << "SnakeApiClient: 解析游戏登录结果";
    qDebug() << "  session_token长度:" << result.sessionToken.length();
    qDebug() << "  player_id:" << result.playerId;
    qDebug() << "  websocket_url:" << result.websocketUrl;

    return result;
}

/**
 * @brief 解析房间信息
 * @param roomData 房间数据JSON
 * @return 房间信息结构
 */
SnakeApiClient::RoomInfo SnakeApiClient::parseRoomInfo(const QJsonObject &roomData)
{
    RoomInfo info;
    info.roomId = roomData["room_id"].toString();
    info.roomName = roomData["room_name"].toString();
    info.creatorId = roomData["creator_id"].toString();
    info.creatorName = roomData["creator_name"].toString();
    info.currentPlayers = roomData["current_players"].toInt();
    info.maxPlayers = roomData["max_players"].toInt();
    info.status = roomData["status"].toString();
    info.gameMode = roomData["game_mode"].toInt();
    info.config = roomData["config"].toObject();
    info.createdAt = roomData["created_at"].toVariant().toLongLong();

    return info;
}

/**
 * @brief 解析玩家统计信息
 * @param statsData 统计数据JSON
 * @return 玩家统计信息结构
 */
SnakeApiClient::PlayerStats SnakeApiClient::parsePlayerStats(const QJsonObject &statsData)
{
    PlayerStats stats;
    stats.playerId = statsData["player_id"].toString();
    stats.username = statsData["username"].toString();
    stats.level = statsData["level"].toInt();
    stats.totalScore = statsData["total_score"].toVariant().toLongLong();
    stats.gamesPlayed = statsData["games_played"].toInt();
    stats.gamesWon = statsData["games_won"].toInt();
    stats.winRate = statsData["win_rate"].toDouble();
    stats.longestSnake = statsData["longest_snake"].toInt();
    stats.totalPlayTime = statsData["total_play_time"].toVariant().toLongLong();
    stats.lastPlayed = statsData["last_played"].toVariant().toLongLong();

    return stats;
}

/**
 * @brief 构建API端点
 * @param path API路径
 * @return 完整的API端点
 */
QString SnakeApiClient::buildEndpoint(const QString &path) const
{
    return QString("/api/v1%1").arg(path);
}

/**
 * @brief 构建客户端信息
 * @return 客户端信息JSON对象
 */
QJsonObject SnakeApiClient::buildClientInfo() const
{
    QJsonObject clientInfo;
    clientInfo["client_type"] = "qt6";
    clientInfo["version"] = QCoreApplication::applicationVersion();
    clientInfo["platform"] = QSysInfo::productType();
    clientInfo["architecture"] = QSysInfo::currentCpuArchitecture();

    QJsonArray capabilities;
    capabilities.append("websocket");
    capabilities.append("chat");
    capabilities.append("spectate");
    capabilities.append("reconnect");
    capabilities.append("compression");
    clientInfo["capabilities"] = capabilities;

    return clientInfo;
}
